﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Xml;

namespace NGIS.Data
{
    public class UdxDataset : UdxNode
    {
        public UdxDataset()
            : base(null, "", EKernelType.EKT_NODE)
        {
            mName = "dataset";
        }

        public bool LoadFromXmlFile(String fileName)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(fileName);
                XmlElement rootEle = doc.DocumentElement;

                int count = rootEle.ChildNodes.Count;
                for (int i = 0; i < count; i++)
                {
                    XmlElement ele = (XmlElement)rootEle.ChildNodes[i];
                    ParseXDO((UdxNode)this, ele);
                }
                return true;
            }
            catch (System.Exception ex)
            {

            }
            return false;
        }

        public bool FormatToXmlFile(String fileName)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                XmlElement element = doc.CreateElement("dataset");
                doc.AppendChild(element);

                int count = this.getChildNodeCount();
                for (int iNode = 0; iNode < count; iNode++)
                {
                    UdxNode tempNode = this.getChildNode(iNode);
                    FormatXDO(tempNode, element);
                }

                doc.Save(fileName);
                return true;
            }
            catch (System.Exception ex)
            {

            }
            return false;
        }

        public bool LoadFromXmlStream(String xml_str)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xml_str);
                XmlElement rootEle = doc.DocumentElement;

                int count = rootEle.ChildNodes.Count;
                for (int i = 0; i < count; i++)
                {
                    XmlElement ele = (XmlElement)rootEle.ChildNodes[i];
                    ParseXDO((UdxNode)this, ele);
                }
                return true;
            }
            catch (System.Exception ex)
            {

            }
            return false;
        }

        public String FormatToXmlStream()
        {
            string xml_str = "";
            try
            {
                XmlDocument doc = new XmlDocument();
                XmlElement element = doc.CreateElement("dataset");
                doc.AppendChild(element);

                int count = this.getChildNodeCount();
                for (int iNode = 0; iNode < count; iNode++)
                {
                    UdxNode tempNode = this.getChildNode(iNode);
                    FormatXDO(tempNode, element);
                }

                xml_str = doc.InnerXml;
            }
            catch (System.Exception ex)
            {
            	
            }
            return xml_str;
        }


        void ParseXDO(UdxNode containerNode, XmlElement element)
        {
            string typeStr = element.GetAttribute("kernelType");
            string name = element.GetAttribute("name");
            EKernelType kernelType = UdxKernel.String2KernelType(typeStr);

            if (typeStr == "int")
            {
                int val = Int32.Parse(element.GetAttribute("value"));
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelIntValue realKernel = (UdxKernelIntValue)node.getKernel();
                realKernel.setTypedValue(val);
            }
            else if (typeStr == "real")
            {
                double val = Double.Parse(element.GetAttribute("value"));
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelRealValue realKernel = (UdxKernelRealValue)node.getKernel();
                realKernel.setTypedValue(val);
            }
            else if (typeStr == "string")
            {
                string val = element.GetAttribute("value");
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelStringValue realKernel = (UdxKernelStringValue)node.getKernel();
                realKernel.setTypedValue(val);
            }
            else if (typeStr == "vector2d")
            {
                string valStr = element.GetAttribute("value");
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelVector2dValue realKernel = (UdxKernelVector2dValue)node.getKernel();
                double x, y;
                string[] ret = valStr.Split(',');
                x = Double.Parse(ret[0]);
                y = Double.Parse(ret[1]);
                realKernel.setTypedValue(x, y);
            }
            else if (typeStr == "vector3d")
            {
                string valStr = element.GetAttribute("value");
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelVector3dValue realKernel = (UdxKernelVector3dValue)node.getKernel();
                double x, y, z;
                string[] ret = valStr.Split(',');
                x = Double.Parse(ret[0]);
                y = Double.Parse(ret[1]);
                z = Double.Parse(ret[2]);
                realKernel.setTypedValue(x, y, z);
            }
            else if (typeStr == "vector4d")
            {
                string valStr = element.GetAttribute("value");
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelVector4dValue realKernel = (UdxKernelVector4dValue)node.getKernel();
                double x, y, z, m;
                string[] ret = valStr.Split(',');
                x = Double.Parse(ret[0]);
                y = Double.Parse(ret[1]);
                z = Double.Parse(ret[2]);
                m = Double.Parse(ret[3]);
                realKernel.setTypedValue(x, y, z, m);
            }
            else if (typeStr == "int_array")
            {
                string valStr = element.GetAttribute("value");
                string[] ret = valStr.Split(',');
                int count = ret.Length;
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelIntArray realKernel = (UdxKernelIntArray)node.getKernel();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    realKernel.addTypedValue(Int32.Parse(ret[iVal]));
                }
            }
            else if (typeStr == "real_array")
            {
                string valStr = element.GetAttribute("value");
                string[] ret = valStr.Split(',');
                int count = ret.Length;
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelRealArray realKernel = (UdxKernelRealArray)node.getKernel();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    realKernel.addTypedValue(Double.Parse(ret[iVal]));
                }
            }
            else if (typeStr == "string_array")
            {
                string valStr = element.GetAttribute("value");
                string[] ret = valStr.Split(';');
                int count = ret.Length;
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelStringArray realKernel = (UdxKernelStringArray)node.getKernel();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    realKernel.addTypedValue(ret[iVal]);
                }
            }
            else if (typeStr == "vector2d_array")
            {
                string valStr = element.GetAttribute("value");
                string[] ret = valStr.Split(';');
                int count = ret.Length;
                {
                    UdxNode node = containerNode.addChildNode(name, kernelType);
                    UdxKernelVector2dArray realKernel = (UdxKernelVector2dArray)node.getKernel();
                    for (int iVal = 0; iVal < count; iVal++)
                    {
                        double x, y;
                        string[] ret1 = ret[iVal].Split(',');
                        x = Double.Parse(ret1[0]);
                        y = Double.Parse(ret1[1]);
                        realKernel.addTypedValue(x, y);
                    }
                }
            }
            else if (typeStr == "vector3d_array")
            {
                string valStr = element.GetAttribute("value");
                string[] ret = valStr.Split(';');
                int count = ret.Length;
                {
                    UdxNode node = containerNode.addChildNode(name, kernelType);
                    UdxKernelVector3dArray realKernel = (UdxKernelVector3dArray)node.getKernel();
                    for (int iVal = 0; iVal < count; iVal++)
                    {
                        double x, y, z;
                        string[] ret1 = ret[iVal].Split(',');
                        x = Double.Parse(ret1[0]);
                        y = Double.Parse(ret1[1]);
                        z = Double.Parse(ret1[2]);
                        realKernel.addTypedValue(x, y, z);
                    }
                }
            }
            else if (typeStr == "vector4d_array")
            {
                string valStr = element.GetAttribute("value");
                string[] ret = valStr.Split(';');
                int count = ret.Length;
                {
                    UdxNode node = containerNode.addChildNode(name, kernelType);
                    UdxKernelVector4dArray realKernel = (UdxKernelVector4dArray)node.getKernel();
                    for (int iVal = 0; iVal < count; iVal++)
                    {
                        double x, y, z, m;
                        string[] ret1 = ret[iVal].Split(',');
                        x = Double.Parse(ret1[0]);
                        y = Double.Parse(ret1[1]);
                        z = Double.Parse(ret1[2]);
                        m = Double.Parse(ret1[3]);
                        realKernel.addTypedValue(x, y, z, m);
                    }
                }
            }
            else if (typeStr == "any" ||
                      typeStr == "list" ||
                      typeStr == "map" ||
                      typeStr == "table")
            {
                UdxNode node = containerNode.addChildNode(name, kernelType);
                int ele_count = element.ChildNodes.Count;
                for (int iChild = 0; iChild < ele_count; iChild++)
                {
                    XmlElement childEle = (XmlElement)element.ChildNodes[iChild];
                    ParseXDO(node, childEle);
                }
            }

        }

        void FormatXDO(UdxNode pNode, XmlElement element)
        {
            EKernelType kernelType = pNode.getKernel().getType();
            string name = pNode.getName();
            XmlDocument doc = element.OwnerDocument;
            XmlElement childEle = doc.CreateElement("XDO");
            element.AppendChild(childEle);
            childEle.SetAttribute("name", name);
            if (kernelType == EKernelType.EKT_INT)
            {
                UdxKernelIntValue realKernel = (UdxKernelIntValue)pNode.getKernel();
                int val = realKernel.getTypedValue();
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", val.ToString());
            }
            else if (kernelType == EKernelType.EKT_REAL)
            {
                UdxKernelRealValue realKernel = (UdxKernelRealValue)pNode.getKernel();
                double val = realKernel.getTypedValue();
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", val.ToString());
            }
            else if (kernelType == EKernelType.EKT_STRING)
            {
                UdxKernelStringValue realKernel = (UdxKernelStringValue)pNode.getKernel();
                string val = realKernel.getTypedValue();
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", val);
            }
            else if (kernelType == EKernelType.EKT_VECTOR2)
            {
                UdxKernelVector2dValue realKernel = (UdxKernelVector2dValue)pNode.getKernel();
                Vector2d val = realKernel.getTypedValue();
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", val.x.ToString() + "," + val.y.ToString());
            }
            else if (kernelType == EKernelType.EKT_VECTOR3)
            {
                UdxKernelVector3dValue realKernel = (UdxKernelVector3dValue)pNode.getKernel();
                Vector3d val = realKernel.getTypedValue();
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", val.x.ToString() + "," + val.y.ToString() + "," + val.z.ToString());
            }
            else if (kernelType == EKernelType.EKT_VECTOR4)
            {
                UdxKernelVector4dValue realKernel = (UdxKernelVector4dValue)pNode.getKernel();
                Vector4d val = realKernel.getTypedValue();
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", val.x.ToString() + "," + val.y.ToString() + "," + val.z.ToString() + "," + val.m.ToString());
            }
            else if (kernelType == (EKernelType.EKT_INT | EKernelType.EKT_LIST))
            {
                UdxKernelIntArray realKernel = (UdxKernelIntArray)pNode.getKernel();
                string valStr = "";
                int count = realKernel.getCount();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    if (iVal != count - 1)
                        valStr += realKernel.getTypedValueByIndex(iVal).ToString() + ", ";
                    else
                        valStr += realKernel.getTypedValueByIndex(iVal).ToString();
                }
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", valStr);
            }
            else if (kernelType == (EKernelType.EKT_REAL | EKernelType.EKT_LIST))
            {
                UdxKernelRealArray realKernel = (UdxKernelRealArray)pNode.getKernel();
                string valStr = "";
                int count = realKernel.getCount();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    if (iVal != count - 1)
                        valStr += realKernel.getTypedValueByIndex(iVal).ToString() + ", ";
                    else
                        valStr += realKernel.getTypedValueByIndex(iVal).ToString();
                }
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", valStr);
            }
            else if (kernelType == (EKernelType.EKT_STRING | EKernelType.EKT_LIST))
            {
                UdxKernelStringArray realKernel = (UdxKernelStringArray)pNode.getKernel();
                string valStr = "";
                int count = realKernel.getCount();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    if (iVal != count - 1)
                        valStr += realKernel.getTypedValueByIndex(iVal).ToString() + ", ";
                    else
                        valStr += realKernel.getTypedValueByIndex(iVal).ToString();
                }
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", valStr);
            }
            else if (kernelType == (EKernelType.EKT_VECTOR2 | EKernelType.EKT_LIST))
            {
                UdxKernelVector2dArray realKernel = (UdxKernelVector2dArray)pNode.getKernel();
                string valStr = "";
                int count = realKernel.getCount();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    Vector2d temp_val = realKernel.getTypedValueByIndex(iVal);
                    if (iVal != count - 1)
                        valStr += temp_val.x + "," + temp_val.y + "; ";
                    else
                        valStr += temp_val.x + "," + temp_val.y;
                }
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", valStr);
            }
            else if (kernelType == (EKernelType.EKT_VECTOR3 | EKernelType.EKT_LIST))
            {
                UdxKernelVector3dArray realKernel = (UdxKernelVector3dArray)pNode.getKernel();
                string valStr = "";
                int count = realKernel.getCount();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    Vector3d temp_val = realKernel.getTypedValueByIndex(iVal);
                    if (iVal != count - 1)
                        valStr += temp_val.x + "," + temp_val.y + "," + temp_val.z + "; ";
                    else
                        valStr += temp_val.x + "," + temp_val.y + "," + temp_val.z;
                }
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", valStr);
            }
            else if (kernelType == (EKernelType.EKT_VECTOR4 | EKernelType.EKT_LIST))
            {
                UdxKernelVector4dArray realKernel = (UdxKernelVector4dArray)pNode.getKernel();
                string valStr = "";
                int count = realKernel.getCount();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    Vector4d temp_val = realKernel.getTypedValueByIndex(iVal);
                    if (iVal != count - 1)
                        valStr += temp_val.x + "," + temp_val.y + "," + temp_val.z + "," + temp_val.m + "; ";
                    else
                        valStr += temp_val.x + "," + temp_val.y + "," + temp_val.z + "," + temp_val.m;
                }
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                childEle.SetAttribute("value", valStr);
            }
            else if (kernelType == EKernelType.EKT_NODE ||
                       kernelType == EKernelType.EKT_LIST ||
                       kernelType == EKernelType.EKT_MAP ||
                       kernelType == EKernelType.EKT_TABLE)
            {
                childEle.SetAttribute("kernelType", UdxKernel.KernelType2String(kernelType));
                int count = pNode.getChildNodeCount();
                for (int iNode = 0; iNode < count; iNode++)
                {
                    UdxNode tempNode = pNode.getChildNode(iNode);
                    FormatXDO(tempNode, childEle);
                }
            }
        }


    }
}
